#include <iostream>
#include <SDL/SDL.h>

#include "omfg_gfx.hpp"

using namespace std;

template< typename BitmapT >
void moo( const BitmapT& b )
{
	for( unsigned int i = 0; i < b.h; ++i )
	{
		for ( unsigned int j = 0; j < b.w; ++j )
		{
			cout << static_cast<int>( b.at(j,i) ) << " ";
		}
		cout << std::endl;
	}
}

void bitmap32ToSDLSurface( Bitmap32* bitmap, SDL_Surface* surface )
{
	SDL_LockSurface(surface);
	
	unsigned int* src = reinterpret_cast<unsigned int*>(bitmap->data);
	unsigned int* dst = reinterpret_cast<unsigned int*>(surface->pixels);
	CopyBlitter<Bitmap32::ColorType> b;
	b.blitBufferToBuffer(dst, src, bitmap->dataSize >> 2 );
	SDL_UnlockSurface(surface);
}


struct FPSLimiter
{
	FPSLimiter()
	{
		lastTime = SDL_GetTicks();
	}
	
	void limitFps( int FPS )
	{
		unsigned int deltaTime = 1000 / FPS;
		unsigned int currentDelta = SDL_GetTicks() - lastTime;
		if ( currentDelta < deltaTime )
		{
			SDL_Delay(deltaTime - currentDelta - 1);
		}
		lastTime = SDL_GetTicks();
	}
	
	unsigned int lastTime;
};

int main( int argc, char *argv[] )
{
	SDL_Init( SDL_INIT_VIDEO | SDL_INIT_AUDIO );
	atexit( SDL_Quit );
	
	SDL_Surface *screen;
	screen = SDL_SetVideoMode( 320, 240, 32, SDL_SWSURFACE );
	Uint8* keys;
	
	typedef vl::ivec P;
	typedef vl::rect R;
	
	
	{
		Bitmap8 img(21,10, 40);
		MaskedCopyBlitter<Bitmap8::ColorType, 0> mb;
		CopyBlitter<Bitmap8::ColorType> b;
		
		cout << endl;
		blendToColor( &img, 0, b );
		hLine( &img, P(-1, 1), 21, 1, b );
		rectFill( &img, R(3, 0, 10, 7), 2, b);
		vLine( &img, P(10, 0), 10, 3, b );
		putPixel( &img, P(4, 7), 4, b );
		//blendToColor( &img, 5, b );
		blit( &img, &img, P(10, 4), P(0, 0), 5, 5, mb );
		
		AddBlitter8 ab;
		//blendToColor( &img, 1, ab );
		blit( &img, &img, P(10, 4), P(0, 0), 5, 5, ab );
		
		blendToColor( &img, 0, b );
		line( &img, P(0,0), P( img.w-1, img.h-1 ), 1, b );
		moo(img);
	}
	cout << endl;
	cout << endl;
	
	
	SDL_PumpEvents();
	keys = SDL_GetKeyState(NULL);
	
	
	CopyBlitter<Bitmap32::ColorType> b;
	ScaledAddBlitter32 ab(4);
	ScaleBlitter8to32 sb;
	
	Bitmap32 img(screen->w,screen->h, 0xFF005000);
	
	Bitmap32 img2(screen->w,screen->h, 0xFF000000);
	unsigned int t1 = SDL_GetTicks();
	/*for ( int i = 0; i < 10000; ++i )
	{
		ScaleBlitter8to32 sb;
		blendToColor( &img, 0x010101, sb );
		//blit(&img2, &img, 0,0,0,0, img.w, img.h, b );
		//bitmap32ToSDLSurface( &img, screen );
	}
	unsigned int t2 = SDL_GetTicks();
	cout << "time was: " << ( 10000 * 1000. ) / t2-t1 << endl;*/
	
	SDL_Flip(screen);
	float moo = 0;
	bool foo = false;
	
	Bitmap32 buffer(screen->w,screen->h,0);
	
	delete buffer.data;
	buffer.data = reinterpret_cast<unsigned char*>(screen->pixels);
	
	vl::vec pos( 130, 120 );
	//buffer.clip.x1 = 100;
	
	int frameCount = 0;
	int lastTime = SDL_GetTicks();
	
	FPSLimiter fpsLimiter;
	
	while ( !keys[SDLK_ESCAPE] )
	{
		SDL_PumpEvents();
		keys = SDL_GetKeyState(NULL);
		if ( keys[SDLK_UP] )
		{
			moo += 2;
			if ( moo > 255 ) moo = 255;
		}
		if ( keys[SDLK_DOWN] )
		{
			moo -= 2;
			if ( moo < 0 ) moo = 0;
		}
		
		if ( keys[SDLK_w] ) pos.y -= 1;
		if ( keys[SDLK_s] ) pos.y += 1;
		if ( keys[SDLK_a] ) pos.x -= 1;
		if ( keys[SDLK_d] ) pos.x += 1;
		//if ( keys[SDLK_e] ) buffer.clip.x1 += 1;
		//if ( keys[SDLK_q] ) buffer.clip.x1 -= 1;
		
		//ab.scale = moo;
		
		blendToColor( &buffer, 0x00, b );
		
		if ( rand()%2 == 0 ) blendToColor( &img, 255, sb );
		
		blit( &buffer, &img, P(0,0), P(0,0), img.w, img.h, b );
		//line( &buffer,  P(pos), P(120,120), 0x00FFFFFF, b );
		circleFill( &img, P(pos), 10, 0x00FF0000, b );
		circleFill( &img, P(pos), 10, 0x00FFFFFF, ab );
		
		ab.scale = 255;
		
		for ( int i = 0; i < 1000; ++i )
		{
			circleFill( &img, P( rand()%640, rand()%480 ), rand()%5, 245, sb );
		}
		
		ab.scale = moo;
		
		blendToColor( &buffer, 0x080FF, ab );

		SDL_Flip(screen);
		
		fpsLimiter.limitFps( 100 );
		
		frameCount++;
		if ( lastTime + 1000 < SDL_GetTicks() )
		{
			cout << "FPS: " << frameCount << endl;
			
			frameCount = 0;
			lastTime = SDL_GetTicks();
		}
	}
	
	return 0;
}
